home *** CD-ROM | disk | FTP | other *** search
- /* restore.c - extract regular files from (tape) archive.
- * This is a part of the Tar program (see file tar.c)
- * Author: T.V.Shaporev
- * Creation date: 11 Mar 1993
- */
- #include <stdio.h>
- #include <errno.h>
-
- #include "sysup.h"
- #include "modern.h"
- #ifdef MODERN
- # include <string.h>
- #else
- char *strncpy();
- int strlen();
- #endif
-
- #ifdef MSDOS
- # include <io.h>
- # include <dos.h>
- # include <stdlib.h>
- # ifdef __TURBOC__
- # include <dir.h>
- # else
- # include <direct.h>
- # endif
- #else
- int access(), creat(), open(), close(), link(), unlink();
- int write(), chown(), utime();
- char *malloc();
- long lseek();
- void free();
- #endif
-
- #include "lzwbits.h"
- #include "lzwhead.h"
- #include "compress.h"
- #include "define.h"
- #include "lzpack.h"
-
- char ofname[MAXTNAME
- #ifdef MSDOS
- +MAXFILE
- #endif
- +1];
-
- void extwrerr()
- {
- (void)fprintf(myout, "Tar: error extracting \'%s\'\n", ofname);
- done(EWRITE);
- }
-
- #ifdef MSDOS
- static void setime __ARGS__(( int, long ));
-
- static void setime(h, mt)
- int h; long mt;
- {
- struct date d;
- struct time t;
- struct ftime f;
-
- if (m_flag) return;
- unixtodos(mt, &d, &t);
- f.ft_tsec = t.ti_sec;
- f.ft_min = t.ti_min;
- f.ft_hour = t.ti_hour;
- f.ft_day = d.da_day;
- f.ft_month = d.da_mon;
- f.ft_year = d.da_year - 1980;
- (void)setftime(h, &f);
- }
-
- #define wcnt_type unsigned short
- #define MAXWARN 8
-
- static renamed = FALSE;
- static wcnt_type wcount = 0;
- static nwarn = 0;
-
- static struct { wcnt_type lru; char wnm[MAXTNAME]; } wlist[MAXWARN];
-
- static void wrename __ARGS__(( char * ));
-
- static void wrename(n)
- char *n;
- {
- register i;
-
- renamed = FALSE;
- for (i=0; i<nwarn; i++) {
- if (strncmp(wlist[i].wnm, n, MAXTNAME) == 0) {
- wlist[i].lru = wcount++; return;
- }
- }
- (void)printf("Tar: warning: renamed to \'%s\'\n", n);
- if (nwarn < MAXWARN) {
- i = nwarn++;
- } else {
- register j;
- /* Find the least recently used entry */
- for (i=0, j=1; j<MAXWARN; j++) {
- if (wlist[j].lru < wlist[i].lru) i = j;
- }
- }
- (void)strncpy(wlist[i].wnm, n, MAXTNAME);
- wlist[i].lru = wcount++;
- }
-
- #define CH_DOT '-'
- #define CH_BAD '$'
-
- static void uname __ARGS__(( char * ));
-
- static void uname(fname) /* convert UNIX file name to DOS */
- char fname[];
- {
- static char invalid[] = "^+=/[]:;\',?*\\<>|\".";
- register char *p = fname;
- register i, offext/* offset to file name extension */;
- register j, limcpy, tmpren;
-
- if (p[1] == ':' && (p[0]>='A' && p[0]<='Z' || p[0]>='a' && p[0]<='z'))
- p += 2;
-
- tmpren = FALSE;
- while (*p) {
- if (*p == '/') {
- ++p; /* Forget dir name changes */ tmpren = FALSE;
- }
-
- for (offext=i=0; p[i] && p[i]!='/'; i++) {
- if (p[i] == '.') {
- if (i == 0) {
- if (p[1]=='.' && p[2]=='/') {
- /* This is '..' directory, skip */ ++i;
- } else if (p[1]!='/') {
- /* This is not current directory */
- p[0] = CH_DOT; tmpren = TRUE;
- }
- } else {
- if (offext) {
- p[offext] = CH_DOT; tmpren = TRUE;
- }
- offext = i;
- }
- } else if (p[i]<=' ' || p[i]>'~' || strchr(invalid, p[i])) {
- p[i] = CH_BAD; tmpren = TRUE;
- }
- }
- if (!offext) offext = i;
- limcpy = MAXTNAME - (int)(p-fname) - offext;
- i -= offext;
- if (offext <= 8) {
- j = offext;
- } else {
- (void)strncpy(p+8, p+offext, i>4 ? 4 : limcpy);
- tmpren = TRUE;
- j = 8;
- }
- if (i <= 4) {
- j += i;
- } else {
- (void)strncpy(p+(offext>8 ? 12 : offext+4), p+i+offext, limcpy-i);
- tmpren = TRUE;
- j += 4;
- }
- p += j;
- }
- if (tmpren) renamed = TRUE;
- }
- #else
- # define setime(h,t)
- # define uname(s)
- #endif
-
- int makedir __ARGS__((char *, int));
- int testdir __ARGS__((char *));
-
- /*ARGSUSED*/ int makedir(p, to_print)
- char *p; int to_print;
- {
- #ifdef UNIX
- # ifdef RMKDIR
- if (mkdir(p, 0777) != 0 && to_print) {
- (void)fprintf(myout, "Tar: can\'t create directory \'%s\'\n", p);
- return ERROR;
- }
- # else
- switch (bincall("mkdir", p)) {
- case 0: break;
- case -1: (void)fprintf(myout, "Tar: fault run mkdir!\n");
- default: done(0);
- }
- # endif
- if (!o_flag) (void)chown(p,(int)st.st_uid,(int)st.st_gid);
- #endif
- #ifdef MSDOS
- if (mkdir(p) != 0 && to_print) {
- (void)fprintf(myout, "Tar: can\'t create directory \'%s\'\n", p);
- return ERROR;
- }
- #endif
- return 0;
- }
-
- int testdir(p)
- char *p;
- {
- register j;
- register k = FALSE;
- #ifndef UNIX
- register char *q = p;
- #endif
- #ifdef MSDOS
- renamed = FALSE;
- #endif
- for (j=1; j<MAXTNAME && p[j]; j++) {/* check directories */
- if (p[j] == '/') {
- p[j] = 0;
- #ifndef UNIX
- uname(q); q = p + j + 1;
- #endif
- if (access(p, 1) < 0) {
- if (makedir(p, TRUE) != 0) return ERROR;
- k = TRUE;
- }
- p[j] = '/';
- }
- }
- #ifdef MSDOS
- if (renamed && v_flag) wrename(p);
- #endif
- return k;
- }
-
- long thisread;
-
- int arcget __ARGS__((void))
- {
- if (v_flag && !(thisread & 07777)) percent(thisread, st.st_size);
- return thisread<st.st_size ? (++thisread, readbyte()) : EOF;
- }
-
- static int o_file, indput;
- static long thiscsum;
-
- static void dstput(c)
- int c;
- {
- thiscsum += c; ((unsigned char *)pk_out)[indput++] = c;
- if (indput >= pksize) {
- if (write(o_file, pk_out, pksize) != pksize) {
- if (v_flag) (void)fprintf(myout, "\n");
- extwrerr();
- }
- indput = 0;
- }
- }
-
- #define savename(s) ((void)strncpy(ofname,(s),MAXTNAME),ofname[MAXTNAME]='\0')
-
- static int newfile __ARGS__(( char *, int ));
-
- static int newfile(name, mode)
- char *name; int mode;
- {
- #ifdef MSDOS
- int h, caccess;
- unsigned cmode;
- register k = 0;
-
- savename(name);
- caccess = o_flag ? O_CREAT+O_EXCL+O_WRONLY+O_BINARY :
- O_CREAT+O_TRUNC+O_WRONLY+O_BINARY;
- cmode = (mode & 0444 ? S_IREAD : 0) |
- (mode & 0222 ? S_IWRITE : 0) |
- (mode & 0111 ? S_IEXEC : 0);
- if ((h = open(name, caccess, cmode)) < 0) {
- if (errno == ENOENT || errno == ENOPATH) {
- if ((k=testdir(name)) == TRUE) h = open(name, caccess, cmode);
- } else if (errno == EEXIST && o_flag) {
- static char del[4] = "^~\'`";
- register unsigned ntry = 0;
- register nb, len, i, j;
- char suffix[5];
-
- if ((len = strlen(name)) > MAXTNAME) goto end;
- for (nb=len; nb>0 && name[nb-1]!='/' && name[nb-1]!=':'; nb--) {
- if (name[nb] == '.') len = nb;
- }
- len -= nb;
- do {
- ++ntry;
- /* Convert number of try into suffix */
- suffix[0] = del[ntry & 3];
- for (i=1, j=ntry>>2; j; j>>=5) {
- suffix[i++] = ((j & 037) < 10 ? '0': 'A'-10) + (j & 037);
- }
- suffix[i] = '\0';
- /* Replace end of the name by suffix */
- if (len < 8) {
- (void)strcat(
- strcpy(ofname+nb+(len+i<8 ? len : 8-i), suffix),
- name+nb+len);
- } else {
- (void)strncpy(ofname+nb+len-i, suffix, i);
- }
- renamed = TRUE;
- h = open(ofname, caccess, cmode);
- } while (h<0 && errno == EEXIST && ntry);
- }
- }
- end:
- if (h < 0) {
- if (k!=ERROR) (void)fprintf(myout,"Tar: can\'t create \'%s\'\n",name);
- } else {
- if (renamed && v_flag) wrename(ofname);
- if ((mode & 0777) == 0) (void)_chmod(name, 1, FA_HIDDEN);
- }
- return h;
- #else
- register j = 0;
- register h;
-
- savename(name);
- do {
- if ((h = creat(name, (int)(mode & 07777))) >= 0) {
- if (!o_flag) (void)chown(name, (int)st.st_uid, (int)st.st_gid);
- return h;
- }
- } while (++j < 2 && testdir(name) == TRUE);
-
- if (j > 1) (void)fprintf(myout, "Tar: can\'t create \'%s\'\n", name);
- return ERROR;
- #endif
- }
-
- static void pfile __ARGS__((char *, long, long));
-
- static void pfile(name, bytes, blocks)
- char name[]; long bytes, blocks;
- {
- if (v_flag) {
- (void)fprintf(myout, "x %s, %ld bytes, %ld tape blocks",
- name, bytes, blocks);
- (void)fflush(myout);
- }
- }
-
- static int xany __ARGS__((void))
- {
- (void)fprintf(stderr, " Extract anyway? ");
- (void)fflush(stderr);
- return YES_NO();
- }
-
- int restore(p)
- register char *p;
- {
- register j;
-
- register long bytes, blocks;
- static char no_mem[] = "\nTar: no memory to unpack.";
- static char e[] = " \n";
- short nx=0, allx; long l=0, xinfo;
- int multy = FALSE; /* Multyvolume processing flag */
- extern int soctul __ARGS__((char*, long*));
- #ifdef MSDOS
- renamed = FALSE;
- #endif
- if (hblock->filetype == GF_MUL) {
- (void)soctul(hblock->x.new.offset, &xinfo);
- multy = TRUE;
- } else {
- if ((nx = isextent(&allx, &xinfo)) > 0) multy = TRUE;
- }
- bytes = codesize > st.st_size ? codesize : st.st_size;
- blocks = (st.st_size + BLKSIZE-1)/BLKSIZE;
- if (pktype == PKfLZW && !multy && st.st_size >= codesize) {
- j = strlen(p);
- if (p[--j] != 'Z' || p[--j] != '.') goto regular;
- p[j] = '\0';
- uname(p);
- if ((o_file = newfile(p, st.st_mode)) < 0) {
- skipfile(); return ERROR;
- }
- pfile(p, bytes, blocks);
- p[j] = '.';
- (void)z_getmem(BITS);
- thisread = 0; indput = 0; thiscsum = 0;
- if ((j = dbegin(arcget)) == 0) {
- do {
- j = dpiece(pk_out, pksize);
- if (j > 0) {
- if (write(o_file, pk_out, j) != j) {
- if (v_flag) (void)fprintf(myout, "\n");
- extwrerr();
- }
- if (v_flag) percent(thisread, st.st_size);
- }
- } while (j == pksize);
- (void)fprintf(myout, v_flag ? e : e+sizeof(e)-2);
- goto xend;
- } else if (j > 0) {
- if (v_flag) (void)fprintf(myout, " is not in compressed format\n");
- } else {
- if (!xany()) done(ESMALL);
- }
- bacouple(); z_relmem();
- }
- regular:
- uname(p);
- if (nx > 1 || (hblock->filetype == GF_MUL && xinfo > 0)) {
- /* Multivolume processing */
- if ((o_file = open(p, O_WRONLY|O_BINARY)) >= 0) {
- savename(p);
- if ((l=lseek(o_file, 0L, 2)) == -1L) {
- (void)fprintf(myout, " Tar: \'%s\' seek error\n", p);
- goto fault;
- }
- if (hblock->filetype == GF_MUL && l != xinfo) {
- if (w_flag) {
- (void)fprintf(stderr,
- " Tar: \'%s\' mismatch size. Append? ", p);
- (void)fflush(stderr);
- if (YES_NO()) goto opened;
- } else {
- (void)fprintf(myout,
- " Tar: warning: \'%s\' mismatch size\n", p);
- }
- l = lseek(o_file, xinfo, 0);
- }
- goto opened;
- } else if (errno == ENOENT) {
- if (w_flag) {
- (void)fprintf(stderr,
- " Tar: \'%s\' does not exist.", p);
- if (!xany()) goto fault;
- } else {
- (void)fprintf(myout,
- " Tar: warning: \'%s\' does not exist\n", p);
- goto fault;
- }
- } else {
- (void)fprintf(myout, "Tar: can\'t append \'%s\'\n", p);
- goto fault;
- }
- }
- if ((o_file = newfile(p, st.st_mode)) < 0) goto fault;
- opened:
- pfile(ofname, bytes, blocks);
-
- if (st.st_size >= codesize || multy) {/* file was not packed */
- if (v_flag) {
- if (nx > 0) {
- (void)fprintf(myout," [extent #%d of %d]", nx, allx);
- } else if (hblock->filetype == GF_MUL) {
- (void)fprintf(myout," [");
- if (l != xinfo)
- (void)fprintf(myout,"from %ld - ", xinfo);
- (void)fprintf(myout,"append @%ld]", l);
- }
- (void)fprintf(myout, "\n");
- }
- (void)readarch(o_file, st.st_size);
- if (nx > 1 && nx == allx && lseek(o_file, 0L, 2) != xinfo) {
- /* last extent extracted, so check for total file size */
- (void)fprintf(myout,"Tar: warning: \'%s\' changed size\n",ofname);
- }
- } else {/* file was packed */
- if (!pk_out) pk_out = malloc(pksize);
- if (!pk_out || lzgetmem()) {
- (void)fprintf(myout, "%s\n", no_mem);
- done(ESMALL);
- }
- thisread = 0; indput = 0; thiscsum = 0;
-
- l = lzdecode(arcget, dstput, codesize);
- (void)fprintf(myout, v_flag ? e : e+sizeof(e)-2);
- if (indput > 0 && write(o_file, pk_out, indput) != indput)
- extwrerr();
- if (l != codesize) {
- (void)fprintf(myout, "Tar: \'%s\' decode error\n", ofname);
- if (!i_flag) done(EINTER);
- }
- if (thiscsum != longcsum) {
- (void)fprintf(myout, "Tar: \'%s\' checksum error\n", ofname);
- }
- }
- xend:
- j = nx > 0 && nx < allx;
- #ifdef MSDOS
- if (!j) setime(o_file, st.st_mtime);
- #endif
- (void)close(o_file);
- return j;
- fault:
- if (o_file >= 0) (void)close(o_file);
- skipfile();
- return ERROR;
- }
-
- void makelink(fname, lname)
- char *fname, *lname;
- {
- #ifdef MSDOS
- # define BUFSIZE 8192
- char *buffer = NULL;
- int bufsize = BUFSIZE;
- #endif
- register j;
-
- #ifdef UNIX
- (void)unlink(fname);
- if ((j = link(lname, fname)) < 0) {
- if (testdir(fname) == TRUE) j = link(lname, fname);
- }
- if (j < 0)
- (void)fprintf(myout,
- "Tar: can\'t link \'%s\' to \'%s\'\n", fname, lname);
- else
- #endif
- #ifdef MSDOS
- if (l_flag) {/* copy file */
- int inp, out;
- char *buffer; int bufsize;
- long rsize, mtime;
-
- if ((buffer = malloc(BUFSIZE)) == NULL) {
- if (pk_out) {
- buffer = pk_out;
- bufsize = pksize;
- } else {
- buffer = (char *)hblock;
- bufsize = BLKSIZE;
- }
- }
- if ((inp = open(lname, O_RDONLY+O_BINARY)) < 0) {
- cantopen(lname); goto quit;
- }
- if ((out = newfile(fname, st.st_mode)) < 0) {
- (void)close(inp); goto quit;
- }
- rsize = st.st_size;
- mtime = st.st_mtime;
- do {
- if ((j = read(inp, buffer, bufsize)) > 0) {
- rsize -= j;
- if (write(out, buffer, j) != j) {
- extwrerr(); j = ERROR;
- }
- }
- } while (j == bufsize);
- if (j >= 0) setime(out, mtime);
- (void)close(out);
- (void)close(inp);
- if (j < 0) goto quit;
- if (v_flag) (void)fprintf(myout, "x %s copied from %s\n", fname, lname);
- if (rsize != 0)
- (void)fprintf(myout,
- "Tar: warning \'%s\' real size differs from the recorded\n",fname);
- } else
- #endif
- if (v_flag) (void)fprintf(myout, "x %s linked to %s\n", fname, lname);
- #ifdef MSDOS
- quit:
- if (buffer != NULL && bufsize == BUFSIZE) free(buffer);
- #endif
- }